﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.OleDb;
using System.IO;
using System.Net;
using System.Xml;
using Com.Toook.Common;

namespace Com.Toook.UpdateRssNews
{
    /// <summary>
    /// UpdateRssNews 的摘要说明
    /// </summary>
    public class UpdateRssNews
    {
        public UpdateRssNews()
        {
            // TODO: 在此处添加构造函数逻辑
            //this.connection = ConfigurationManager.ConnectionStrings["RssNewsString"].ConnectionString
            //    + HttpContext.Current.Server.MapPath("~/App_Data/rss.mdb");
            //this.connection = //GetConfigContent.ConnectionStringNews;
            //    "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
            //    HttpContext.Current.Server.MapPath("~/App_Data/rss.mdb");
        }
        private string connection;

        public void UpdateAllSiteNews()
        {
            int sid = 0, showCount = 0, timeSpan = 0, errorN = 0;
            string url = string.Empty, tempId = string.Empty;
            DateTime expiryTime = DateTime.Now;

            string command = "select top 1 SiteId, Url, NewsCount, ExpiryTime, TimeSpan, ErrorN,newsPageTempId from Sites where IsLatest=true order by ExpiryTime";
            OleDbConnection cnn = new OleDbConnection(connection);
            OleDbCommand cmd = new OleDbCommand(command, cnn);
            OleDbDataReader reader = null;
            try
            {
                cnn.Open();
                reader = cmd.ExecuteReader();
                if(reader.Read())
                {
                    sid = int.Parse(reader[0].ToString());
                    url = reader.GetString(1);
                    showCount = int.Parse(reader[2].ToString());
                    expiryTime = reader.GetDateTime(3);
                    timeSpan = int.Parse(reader[4].ToString());
                    errorN = int.Parse(reader[5].ToString());
                    tempId = reader[6].ToString();
                    reader.Close();
                    cnn.Close();
                }
            }
            catch(Exception ex)
            {
                LogHelper.Log.Error("网站App Error. ", ex);
            }
            finally{
                if(reader != null){ reader.Close();}
                cnn.Close();
            }            

            try
            {
                if(expiryTime <= DateTime.Now)
                {
                    DownloadXml(sid, url, showCount, timeSpan, tempId);//, connection
                }
            }
            catch(Exception xmlDownEx)
            {
                string error = xmlDownEx.Message;
                error = error.Replace('\'', ' ');
                string errorCommand = "insert into errors(SiteId,Description,ErrorTime,Url) values(" + sid.ToString() + ",'" + error + "','" + DateTime.Now.ToString() + "','" + url + "')";
                LogHelper.Log.Error("下载Rss xml 错误。" + errorCommand, xmlDownEx);
                cmd.CommandText = errorCommand;
                cnn.Open();
                cmd.ExecuteNonQuery();
                cnn.Close();
                UpdateExpiryTime(sid, timeSpan * 2);////下载或插入出错时，更新时间，加2小时。 , connection
            }
        }
        /// <summary>
        /// 手动更新单个站点的新闻
        /// </summary>
        /// <param name="sid">站点ID</param>
        /// <param name="url">站点地址</param>
        /// <param name="showCount">显示新闻的条数</param>
        /// <param name="timeSpanMinute">增加的时间间隔</param>
        /// <returns>返回值，正常为ok出错为异常原因</returns>
        public string UpdateOneSite(int sid, string url, int showCount, int timeSpanMinute)
        {
            string result = "ok";
            try
            {
                DownloadXml(sid, url, showCount, timeSpanMinute, "无");
            }
            catch(Exception e)
            {
                result = e.Message;
            }
            return result;
        }
        protected void DownloadXml(int sid, string url, int showCount, int timeSpan, string templateId)//, string connection
        {
            string haveDetail = templateId == "无" ? "3" : "0";
            byte[] rssXml = new WebClient().DownloadData(url);
            XmlDocument doc = new XmlDocument();
            doc.Load(new MemoryStream(rssXml));
            XmlNodeList items = doc.SelectNodes("rss/channel/item");
            string title, link, pubDate, content="";
            int sameCount = 0, insertCount = showCount;
            int maxNumber = GetMaxInsertNumber();//取得RssNews中最大的InsertNumber值，即最后插入的值connection
            
            foreach(XmlNode item in items)
            {
                XmlNode linkNode = item.SelectSingleNode("link");                
                if(linkNode == null)
                {
                    linkNode = item.SelectSingleNode("guid");//大洋网没有link,是guid
                }
                if(linkNode == null)
                {
                    LogHelper.Log.Error("网站没有链接地址rss/channel/item/link或者guid。sid=" + sid.ToString() + ", url=" + url);
                    continue;
                }
                link = linkNode.InnerText;
                string haveCmd = "SELECT count(link) AS linkCount FROM RssNews WHERE siteId=" + sid.ToString() + " and link='" + link + "'";
                OleDbConnection cnnhave = new OleDbConnection(connection);
                OleDbCommand cmdhave = new OleDbCommand(haveCmd, cnnhave);
                cnnhave.Open();
                int counter = (int)cmdhave.ExecuteScalar();
                cnnhave.Close();
                if(counter > 0)
                {
                    if(++sameCount > 3) //如果连续三个都已经有，跳出循环，更新站点时间。
                        break;
                    else
                        continue;
                }
                else
                {
                    title = item.SelectSingleNode("title").InnerText;
                    pubDate = ParsePubDate(item.SelectSingleNode("pubDate").InnerText);
                    XmlNode contentNode = item.SelectSingleNode("description");//大洋网有完整的内容
                    if(contentNode != null)
                    {
                        content = contentNode.InnerText;
                    }
                    int num = (maxNumber + insertCount--);
                    sameCount = 0;//有新的，将 sameCount 重置为零

                    OleDbConnection cnn = new OleDbConnection(connection);
                    OleDbCommand com = new OleDbCommand("insert into RssNews(title,link,pubDate,siteId,insertNumber,haveNewsDetail, content) " +
                        "values(?, ?,'" + pubDate + "','" + sid + "'," + num.ToString() + "," + haveDetail + ", ?)", cnn);
                    com.Parameters.Add("title", OleDbType.VarWChar, 50).Value = title;
                    com.Parameters.Add("link", OleDbType.VarChar, 250).Value = link;
                    com.Parameters.Add("content", OleDbType.LongVarWChar).Value = content;

                    try
                    {
                        cnn.Open();
                        com.ExecuteNonQuery();
                    }
                    catch(Exception exx)
                    {
                        insertCount++;
                        LogHelper.Log.Error("插入新闻失败.title=" + title +", link=" + link + ", sid=" + sid + ", content=" + content, exx);
                    }
                    finally
                    {
                        cnn.Close();
                    }
                    if(insertCount == 0)//加够 showCount 条后，跳出。
                    {
                        break;
                    }
                }
            }//end foreach

            int RssNewsCount = GetRssNewsCount(sid); //get news number, where news is not ad  (adNumber = 2), connection
            while(RssNewsCount > showCount)
            {
                try
                {
                    DeleteTop(sid);  //delete top one news,which is not ad , connection
                }
                catch(Exception deleteEx)
                {
                    string error = deleteEx.Message;
                    error = error.Replace('\'', ' ');
                    string errorCommand = "insert into errors(SiteId,Description,ErrorTime,Url) values(" + sid.ToString() + ",'我的程序删除数据出错，原因：" + error + "','" + DateTime.Now.ToString() + "','" + url + "')";
                    OleDbConnection cnnInsert = new OleDbConnection(connection);
                    OleDbCommand cmdInsert = new OleDbCommand(errorCommand, cnnInsert);//
                    cmdInsert.CommandText = errorCommand;
                    cnnInsert.Open();
                    cmdInsert.ExecuteNonQuery();
                    cnnInsert.Close();
                }
                RssNewsCount--;

            }
            UpdateExpiryTime(sid, timeSpan);//, connection
        }
        /// <summary>
        /// 将RSS源的日期处理成某月某日
        /// </summary>
        /// <param name="pubDate">RSS的日期</param>
        /// <returns>月日</returns>
        protected string ParsePubDate(string pubDate)
        {
            string result;
            try
            {
                DateTime date = DateTime.Parse(pubDate);
                string hour, minute;
                hour = (date.Hour < 10) ? "0" + date.Hour.ToString() : date.Hour.ToString();
                minute = (date.Minute < 10) ? "0" + date.Minute.ToString() : date.Minute.ToString();
                result = date.Month.ToString() + "月" + date.Day.ToString() + "日" + hour + ":" + minute;
            }
            catch(Exception ex)
            {
                result = DateTime.Now.Month.ToString() + "月" + DateTime.Now.Day.ToString() + "日";
            }
            return result;
        }
        protected void DeleteTop(int sid)//, string connection
        {
            OleDbConnection cnn = new OleDbConnection(connection);
            OleDbCommand cmd = new OleDbCommand("DeleteMin", cnn);//
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add("siteId", OleDbType.Integer, 4).Value = sid;
            cnn.Open();
            cmd.ExecuteScalar();
            cnn.Close();
        }
        protected int GetRssNewsCount(int sid)//, string connection
        {
            OleDbConnection cnn = new OleDbConnection(connection);
            OleDbCommand cmd = new OleDbCommand("GetRssNewsCount", cnn);
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add("siteId", OleDbType.Integer, 4).Value = sid;

            cnn.Open();
            int number = (int)cmd.ExecuteScalar();
            cnn.Close();
            return number;
        }
        protected int GetMaxInsertNumber()//string connection
        {
            OleDbConnection cnn = new OleDbConnection(connection);
            OleDbCommand cmd = new OleDbCommand("GetMaxInsertNumber", cnn);
            cmd.CommandType = CommandType.StoredProcedure;
            cnn.Open();
            object num = cmd.ExecuteScalar();
            int number = 0;
            if(num != null && !string.IsNullOrEmpty(num.ToString()))
            {
                int.TryParse(num.ToString(), out number);
            }
            cnn.Close();
            return number;
        }

        protected void UpdateExpiryTime(int sid, int timeSpan)//, string connection
        {
            OleDbConnection cnn = new OleDbConnection(connection);
            string command = "update Sites set ExpiryTime='" + DateTime.Now.AddMinutes(timeSpan) + "' where SiteId=" + sid.ToString();
            OleDbCommand cmd = new OleDbCommand(command, cnn);
            cnn.Open();
            int count = cmd.ExecuteNonQuery();
            cnn.Close();
        }
    }
}